package com.xiehua.task.client;

import com.xiehua.task.annotation.FixedTaskExecutor;
import com.xiehua.task.annotation.Task;
import com.xiehua.task.job.pool.DelayJob;
import com.xiehua.task.job.pool.FixedJob;
import com.xiehua.task.job.pool.Job;
import com.xiehua.task.msg.TaskRegReqBody;
import com.xiehua.task.prop.XiehuaConfig;
import com.xiehua.task.protocol.TaskPacket;
import com.xiehua.task.protocol.Type;
import com.xiehua.task.utils.ScanUtil;
import com.xiehua.task.utils.StringUtils;
import org.tio.client.AioClient;
import org.tio.client.ClientChannelContext;
import org.tio.client.ClientGroupContext;
import org.tio.client.ReconnConf;
import org.tio.client.intf.ClientAioListener;
import org.tio.core.Aio;
import org.tio.core.Node;
import org.tio.utils.json.Json;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.xiehua.task.prop.XiehuaConfig.*;


public class ClientApp {


    public static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
        //check config
        Map<String,String> configMap = XiehuaConfig.getInstance();
        //通信使用的cid,key
        String  cid = configMap.get(XiehuaConfig.KEY_CLIENT_CID);
        if(StringUtils.isEmpty(cid)) throw new RuntimeException("cid参数为空,请配置相关参数:task.client.cid");
        String  key = configMap.get(XiehuaConfig.KEY_CLIENT_SECRET_KEY);
        if(StringUtils.isEmpty(key)) throw new RuntimeException("secret key参数为空,请配置相关参数:task.client.secret_key");
        //init connect
        ClientHandler aioClientHandler = new ClientHandler();
        ClientAioListener aioListener = new ClientListener();

        ReconnConf reconnConf = new ReconnConf(Long.parseLong(configMap.get(XiehuaConfig.KEY_CLIENT_INTERVAL)));
        // 一组连接共用的上下文对象
        ClientGroupContext clientGroupContext = new ClientGroupContext(aioClientHandler, aioListener, reconnConf);
        clientGroupContext.setHeartbeatTimeout(Integer.parseInt(configMap.get(XiehuaConfig.KEY_SERVER_TIMEOUT)));
        AioClient aioClient = new AioClient(clientGroupContext);
        aioClient.setClientGroupContext(clientGroupContext);
        // 服务器节点
        Node serverNode = new Node(configMap.get(XiehuaConfig.KEY_SERVER_HOST), Integer.parseInt(configMap.get(XiehuaConfig.KEY_SERVER_PORT)));
        ClientChannelContext clientChannelContext = aioClient.connect(serverNode);



        //延迟任务注册
        regTask(clientChannelContext ,delayjob(),cid,key);
        //定时任务注册
        fixedjob().forEach(s ->{
            try {
                regTask(clientChannelContext,s,cid,key);
            }catch (UnsupportedEncodingException e){
                e.printStackTrace();
            }
        });
    }

    private static void regTask(ClientChannelContext clientChannelContext,Job job,String cid,String key) throws UnsupportedEncodingException {
        TaskRegReqBody taskRegReqBody = new TaskRegReqBody();
        taskRegReqBody.setJobContent(Json.toJson(job));
        taskRegReqBody.setType(job.getType());
        String bizData = Json.toJson(taskRegReqBody);

        TaskPacket packet = new TaskPacket(Type.TASK_REG_REQ, cid);
        packet.setBody(bizData.getBytes(TaskPacket.CHARSET));
        packet.signData(bizData, key);
        Aio.send(clientChannelContext, packet);

    }

    public static DelayJob delayjob() {
        Map<String,String> configMap = XiehuaConfig.getInstance();
        String jobBody = "哈哈，我是第一个任务的内容";
        DelayJob job = new DelayJob(configMap.get(KEY_CLIENT_TOPIC), jobBody, 60L);
        return job;
    }

    public static List<FixedJob> fixedjob() throws IOException {
        Map<String,String> configMap = XiehuaConfig.getInstance();
        List<Class<?>> list = ScanUtil.scan(configMap.get(KEY_CLIENT_FIXED_TASK_PACKAGE));
        List<Class<?>> list2 = ScanUtil.getClassWithAnnotation(list, Task.class);
        List<FixedTaskExecutor> list3 = ScanUtil.getFixedTaskExecutor(list2);
        List<FixedJob> jobs = list3.stream().map(s -> s.getExecutors().stream().map(t -> new FixedJob(configMap.get(KEY_CLIENT_TOPIC), s.getClassName(), t.getName(), t.getCron())).collect(Collectors.toList())).flatMap(m -> m.stream()).collect(Collectors.toList());
        return jobs;
    }


}
